package elastic

func NewTermsAggregation(field string) *Aggregation {
	return &Aggregation{
		Terms: &Term{
			Field: field,
			Size:  2147483647,
		},
	}
}

func NewAvgAggregation(field string) *Aggregation {
	return &Aggregation{
		Avg: &Avg{Field: field},
	}
}

func NewRangeAggregation(field string) *Aggregation {
	return &Aggregation{
		Range: &RangeAgg{
			Field:  field,
			Ranges: make([]*SplitItem, 0),
		},
	}
}

func NewCardinalityAggregation(field string) *Aggregation {
	return &Aggregation{
		Cardinality: &Cardinality{
			Field: field,
		},
	}
}

type Aggregation struct {
	Terms       *Term                   `json:"terms,omitempty"`
	Aggregation map[string]*Aggregation `json:"aggs,omitempty"`
	Avg         *Avg                    `json:"avg,omitempty"`
	Range       *RangeAgg               `json:"range,omitempty"`
	Cardinality *Cardinality            `json:"cardinality,omitempty"`
}

type RangeAgg struct {
	Field  string       `json:"field,omitempty"`
	Ranges []*SplitItem `json:"ranges,omitempty"`
}

type SplitItem struct {
	Key  string      `json:"key"`
	From interface{} `json:"from"`
	To   interface{} `json:"to"`
}

type Avg struct {
	Field string `json:"field"`
}

type Cardinality Avg

type Term struct {
	Field string      `json:"field,omitempty"`
	Size  uint        `json:"size,default=2147483647"`
	Order interface{} `json:"order,omitempty"`
}

func (a *Aggregation) SubAggregation(name string, agg *Aggregation) *Aggregation {
	if a.Aggregation == nil {
		a.Aggregation = make(map[string]*Aggregation)
	}
	a.Aggregation[name] = agg
	return a
}

func (a *Aggregation) RangeItem(item *SplitItem) *Aggregation {
	if a.Range.Ranges == nil {
		a.Range.Ranges = make([]*SplitItem, 0)
	}
	a.Range.Ranges = append(a.Range.Ranges, item)
	return a
}

func (a *Aggregation) SizeTerms(size uint) *Aggregation {
	a.Terms.Size = size
	return a
}

func (a *Aggregation) OrderTerms(item interface{}) *Aggregation {
	a.Terms.Order = item
	return a
}
